﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing.Design;
using System.ComponentModel.Design;
using System.ComponentModel;
using System.Windows.Forms.Design;
using System.Windows.Forms;
using System.Data;

namespace ProgNetComponentsDx.Validation.Design
{
    public class ValidationRulesForTableCollectionEditor : UITypeEditor
    {
        private ITypeDescriptorContext currentContext;
        private bool ignoreChangedEvents;
        private bool ignoreChangingEvents;
        IWindowsFormsEditorService edSvc = null;
        protected ITypeDescriptorContext Context
        {
            get
            {
                return this.currentContext;
            }
        }
       
        public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.Modal;
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            IDesignerHost designerHost = null;
            if (provider != null)
            {
                edSvc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
                if (edSvc != null)
                {
                    this.currentContext = context;
                    
                    ITypeDescriptorContext descriptorContext = this.currentContext;
                    this.ignoreChangingEvents = false;
                    this.ignoreChangedEvents = false;
                    designerHost = provider.GetService<IDesignerHost>();
                    ValidationSettings settings = context.Instance as ValidationSettings;
                    DataSet ds = null;
                    DataTable dt = null;
                    ValidationRulesForTableCollection rules = value as ValidationRulesForTableCollection;
                    if (settings == null)
                    {
                        if (context.Instance is ValidationComponent)
                        {
                            ds = ((ValidationComponent)context.Instance).DataSource;
                            string dataMember = ((ValidationComponent)context.Instance).DataMember;
                            if (ds != null && dataMember.IsNotNull() && ds.Tables.Contains(dataMember))
                                dt = ds.Tables[dataMember];
                        }
                    }
                    else
                    {
                        ds = settings.Owner as DataSet;
                        dt = settings.Owner as DataTable;
                    }
                    using (ValidationRulesEditor f = new ValidationRulesEditor(designerHost, rules, ds, dt))
                    {
                        DesignerTransaction designerTransaction = null;
                        bool flag = true;
                        IComponentChangeService componentChangeService = null;

                        try
                        {
                            try
                            {
                                if (designerHost != null)
                                    designerTransaction = designerHost.CreateTransaction();
                            }
                            catch (CheckoutException ex)
                            {
                                if (ex == CheckoutException.Canceled)
                                    return value;
                                else
                                    throw new Exception("Exception occured", ex);
                            }
                            componentChangeService = designerHost != null ? (IComponentChangeService)designerHost.GetService(typeof(IComponentChangeService)) : (IComponentChangeService)null;
                            if (componentChangeService != null)
                            {
                                componentChangeService.ComponentChanged += new ComponentChangedEventHandler(this.OnComponentChanged);
                                componentChangeService.ComponentChanging += new ComponentChangingEventHandler(this.OnComponentChanging);
                            }
                            if (edSvc.ShowDialog(f) != DialogResult.OK)
                                flag = false;
                            else
                                f.MergeResults();
                        }
                        catch
                        {

                        }
                        finally
                        {
                            this.currentContext = descriptorContext;
                            if (designerTransaction != null)
                            {
                                if (flag)
                                    designerTransaction.Commit();
                                else
                                    designerTransaction.Cancel();
                            }
                            if (componentChangeService != null)
                            {
                                componentChangeService.ComponentChanged -= new ComponentChangedEventHandler(this.OnComponentChanged);
                                componentChangeService.ComponentChanging -= new ComponentChangingEventHandler(this.OnComponentChanging);
                            }
                        }
                    }
                }
            }
            if (this.Context != null)
            {
                this.Context.OnComponentChanging();
                this.Context.OnComponentChanged();
            }
            
            return value;
        }

        private void OnComponentChanged(object sender, ComponentChangedEventArgs e)
        {
            if (!this.ignoreChangedEvents && sender != this.Context.Instance)
            {
                this.ignoreChangedEvents = true;
                this.Context.OnComponentChanged();
            }
        }

        private void OnComponentChanging(object sender, ComponentChangingEventArgs e)
        {
            if (!this.ignoreChangingEvents && sender != this.Context.Instance)
            {
                this.ignoreChangingEvents = true;
                this.Context.OnComponentChanging();
            }
        }

    }
}
